package com.bestvike.stone.core.lang;

import com.bestvike.linq.IEnumerable;
import com.bestvike.linq.Linq;

/**
 * Created by 许崇雷 on 2019-02-12.
 */
public final class URLUtils {
    private static final char[] CHARS = new char[]{
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
            'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
            'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
            'y', 'z', '0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'A', 'B', 'C', 'D',
            'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
            'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
            'U', 'V', 'W', 'X', 'Y', 'Z'};

    private URLUtils() {
    }

    /**
     * 获取短 URL 地址
     *
     * @param url 原始 URL 地址
     * @return 短 URL 地址序列
     */
    public static IEnumerable<String> tiny(final String url) {
        return tiny(url, null, null);
    }

    /**
     * 获取短 URL 地址
     *
     * @param url    原始 URL 地址
     * @param prefix 前缀
     * @param suffix 后缀
     * @return 短 URL 地址序列
     */
    public static IEnumerable<String> tiny(final String url, final String prefix, final String suffix) {
        String value = StringUtils.EMPTY;
        if (prefix != null)
            value += prefix;
        if (url != null)
            value += url;
        if (suffix != null)
            value += suffix;

        //32 字符
        final String md5 = DigestUtils.md5Hex(value);
        return Linq.range(0, 4)
                .select(index -> {
                    //8 个字符
                    String partMd5 = md5.substring(index << 3, (index + 1) << 3);
                    //转换为整型,取 30 位
                    long partMd5Long = Long.parseLong(partMd5, 16) & 0x3FFFFFFF;
                    String output = StringUtils.EMPTY;
                    //每 5 位进行进制转换(顺序是反的)
                    for (int j = 0; j < 6; j++) {
                        long k = partMd5Long & 0x3D;
                        //把取得的字符相加
                        output += CHARS[(int) k];
                        //为下次循环准备
                        partMd5Long = partMd5Long >> 5;
                    }
                    return output;
                });
    }
}
